package se.recept.kollen.module.bean;

import com.google.inject.Inject;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.persistence.EntityManager;
import net.sourceforge.stripes.action.DefaultHandler;
import net.sourceforge.stripes.action.ForwardResolution;
import net.sourceforge.stripes.action.HandlesEvent;
import net.sourceforge.stripes.action.Resolution;
import net.sourceforge.stripes.action.UrlBinding;
import net.sourceforge.stripes.validation.Validate;
import net.sourceforge.stripes.validation.ValidateNestedProperties;
import se.recept.kollen.model.Product;
import se.recept.kollen.model.ProductCategory;
import se.recept.kollen.module.extension.FragmentResolution;
import se.recept.kollen.module.extension.NoContentResolution;

/**
 *
 * @author jocke
 */
@UrlBinding("/action/product")
public class ProductActionBean extends DefaultActionBean {

    private static final Logger LOG = Logger.getLogger(LoginActionBean.class.getName());

    @ValidateNestedProperties({
        @Validate(field = "name", on = "addCategory", required = true)
    })
    private ProductCategory productCategory;

    private ProductCategory mainCategory;

    @Validate(on = "deleteCategory", required = true)
    private Integer productCategoryId;

    private static final int PRODUCT_MAX_RESULT = 200;

    @ValidateNestedProperties({
        @Validate(field = "id", on = "removeProducts", required = true)
    })
    private List<Product> products;

    @Validate(on = "filterByActive", required = true)
    private boolean showActive;

    @Validate(on = "filterBySearch", required = true, trim = true, minlength = 2)
    private String searchText;

    @Inject
    private EntityManager em;

    public ProductCategory getProductCategory() {
        return productCategory;
    }

    public void setProductCategory(ProductCategory productCategory) {
        this.productCategory = productCategory;
    }

    public Integer getProductCategoryId() {
        return productCategoryId;
    }

    public void setProductCategoryId(Integer productCategoryId) {
        this.productCategoryId = productCategoryId;
    }

    public ProductCategory getMainCategory() {
        return mainCategory;
    }

    public void setMainCategory(ProductCategory mainCategory) {
        this.mainCategory = mainCategory;
    }

    public List<Product> getProducts() {
        return products;
    }

    public void setProducts(List<Product> products) {
        this.products = products;
    }

    public boolean isShowActive() {
        return showActive;
    }

    public void setShowActive(boolean showActive) {
        this.showActive = showActive;
    }

    public String getSearchText() {
        return searchText;
    }

    public void setSearchText(String searchText) {
        this.searchText = searchText;
    }

    @DefaultHandler
    public Resolution list() {
        populateProducts();
        populateCategories();
        return new ForwardResolution(Pages.PRODUCT_OVERVIEW);

    }

    private void populateCategories() {
        final List<ProductCategory> categories = em.createNamedQuery(ProductCategory.FIND_BY_CUSTOMER, ProductCategory.class)
                .setParameter("customer", getCustomer())
                .getResultList();
        getContext().getRequest().setAttribute("categories", categories);
    }

    private void populateProducts() {
        products = em.createNamedQuery(Product.FIND_ALL, Product.class).setMaxResults(PRODUCT_MAX_RESULT).getResultList();
        getContext().getRequest().setAttribute("products", products);
    }

    @HandlesEvent("addCategory")
    public Resolution addCategory() {

        ProductCategory parent = null;

        productCategory.setCustomer(getCustomer());

        if (mainCategory != null && mainCategory.getId() != null) {
            parent = em.find(ProductCategory.class, mainCategory.getId());
            productCategory.setMainCategory(parent);
        }

        LOG.log(Level.INFO, "Will add product category {0}", productCategory);

        em.persist(productCategory);

        if (parent != null) {
            List<ProductCategory> parentSubs = (parent.getSubCategories() == null ? new ArrayList<ProductCategory>() : parent.getSubCategories());
            parentSubs.add(productCategory);
            em.merge(parent);
        }

        populateCategories();

        return new FragmentResolution();
    }

    @HandlesEvent("deleteCategory")
    public Resolution deleteCategory() {

        ProductCategory category = em.find(ProductCategory.class, productCategoryId);

        if (category != null) {
            em.remove(category);
        }

        populateCategories();

        LOG.log(Level.INFO, "Will remove products {0}", productCategoryId);

        return new FragmentResolution();
    }

    @HandlesEvent("deleteProducts")
    public Resolution deleteProducts() {

        LOG.log(Level.INFO, "Will remove {0} ", products);

        for (Product product : products) {
            if (product != null) {
                em.remove(em.find(Product.class, product.getId()));
            }
        }

        populateProducts();

        return new FragmentResolution();
    }

    @HandlesEvent("filterByActive")
    public Resolution filterByActive() {
        LOG.log(Level.INFO, "Filter  by active {0} ", showActive);

        if (showActive) {

            products = em.createNamedQuery(Product.FIND_BY_ACTIVE, Product.class).setParameter("active", showActive)
                    .setMaxResults(PRODUCT_MAX_RESULT).getResultList();

            getContext().getRequest().setAttribute("products", products);

        } else {
            populateProducts();
        }

        return new FragmentResolution();
    }

    @HandlesEvent("filterBySearch")
    public Resolution filterBySearch() {
        LOG.log(Level.INFO, "Filter  by search {0} ", searchText);
        products = em.createNamedQuery(Product.FIND_BY_LIKE_NAME, Product.class).setParameter("name", "%" + searchText + "%")
                .setMaxResults(PRODUCT_MAX_RESULT).getResultList();
        getContext().getRequest().setAttribute("products", products);
        return new FragmentResolution();
    }
}
